home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
nn.zip
/
MENU.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-31
|
31KB
|
1,472 lines
/*
* selection mode menu
*/
#include "config.h"
#include "articles.h"
#include "term.h"
#include "keymap.h"
#include "menu.h"
#include "regexp.h"
export int preview_window = 0; /* size of preview window */
export int fmt_linenum = 1; /* menu line format */
export int fmt_rptsubj = 0; /* repeat identical subjects if !0 */
export int novice = 1; /* novice mode -- use extended prompts */
export int long_menu = 0; /* don't put empty lines around menu lines */
export int delay_redraw = 0; /* prompt again if :-command clears screen */
export int slow_mode = 0; /* mark selected articles with *s */
export int re_layout = 0; /* Re: format presentation on menus */
export int collapse_subject = 25; /* collapse long subjects at position */
export int conf_group_entry = 0; /* ask whether group should be entered */
export int auto_preview_mode = 0; /* preview rather than select */
export char *delayed_msg = NULL; /* give to msg() after redraw */
export long dl_msg_arg = 0; /* optional arg to delayed_msg */
import also_read_articles;
import merged_menu;
#ifdef NNTP
import int use_nntp; /* is nntp in use? */
#endif
extern group_completion();
static regexp *regular_expr = NULL;
static int firstl; /* first menu line */
static article_number firsta; /* first article on menu (0 based) */
static int cura; /* current article */
static int next_cura; /* article to become cura if >= 0 */
static int numa; /* no of articles on menu - 1 */
#define INTERVAL1 ('z' - 'a' + 1)
#define INTERVAL2 ('9' - '0' + 1)
char ident[] = "abcdefghijklmnopqrstuvwxyz0123456789";
char Ident[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ&&&&&&&&&&";
/* mark commands */
#define OFF 0
#define ON 1
#define TOGGLE 2
#define INIT 3
#define SAVED 4
#define REMOVE 5
#define CANCEL 6
#define ON_LEAVE 7
#define ON_READ 8
static int how;
static mark()
{
register article_header *ah;
int lno, curhow, must_print, lnum, lsubj, lname;
ah = articles[firsta + cura];
curhow = (ah->flag & A_SELECT) ? ON : OFF;
if (how == curhow) return;
lno = firstl + cura;
must_print = !slow_mode && STANDOUT;
toggle:
switch (how) {
case TOGGLE:
how = (curhow == ON) ? OFF : ON;
goto toggle;
case ON:
if (ah->flag & A_CANCEL) {
if (curhow == OFF) return;
how = OFF;
goto toggle;
}
ah->flag &= ~(A_LEAVE | A_READ);
ah->flag |= A_SELECT;
break;
case OFF:
ah->flag &= ~(A_SELECT | A_AUTO);
break;
case INIT:
gotoxy(0, lno);
putchar(ident[cura]);
how = curhow;
must_print = 1;
break;
case SAVED:
gotoxy(0, lno);
putchar(Ident[cura]);
return;
case REMOVE:
gotoxy(0, lno);
clrline();
return;
case CANCEL:
if (must_print && (ah->flag & A_SELECT)) {
ah->flag &= ~(A_SELECT | A_AUTO);
break;
}
ah->flag &= ~(A_SELECT | A_AUTO | A_LEAVE | A_LEAVE_NEXT | A_READ);
gotoxy(1, lno);
putchar((ah->flag & A_CANCEL) ? '#' : ' ');
return;
case ON_READ:
if (cura < 0 || cura > numa) return;
gotoxy(1, lno);
putchar((ah->flag & A_READ) ? '.' : ' ');
return;
case ON_LEAVE:
if (cura < 0 || cura > numa) return;
gotoxy(1, lno);
putchar((ah->flag & A_LEAVE) ? '+' :
(ah->flag & A_LEAVE_NEXT) ? '=' : ' ');
return;
}
if (cura < 0 || cura > numa) return;
/* menu line formats:
1 3 8 10 20 22 xx
: : : : : : :
0 id name subject +lines
1 id name lines subject
2 id lines subject
3 id subject
4 id name:8 subject
*/
if (must_print) {
if (fmt_linenum > 5) fmt_linenum = 1;
if (ah->flag & (A_CANCEL | A_LEAVE | A_LEAVE_NEXT | A_READ)) {
gotoxy(1, lno);
putchar(
(ah->flag & A_READ) ? '.' :
(ah->flag & A_LEAVE) ? '+' :
(ah->flag & A_CANCEL) ? '#' :
'='
);
} else
if (how == ON && !slow_mode) {
if (so_gotoxy(1, lno, 1) == 0) putchar('*');
} else {
gotoxy(1, lno);
putchar(how == ON ? '*' : ' ');
}
if (ah->lines < 10) lnum = 1; else
if (ah->lines < 100) lnum = 2; else
if (ah->lines < 1000) lnum = 3; else
if (ah->lines < 10000) lnum = 4; else lnum = 5;
lsubj = Columns - cookie_size - 2; /* ident char + space */
switch (fmt_linenum) {
case 0:
lsubj -= NAME_LENGTH + 1 + 2 + lnum; /* name. .subj. +.lines */
so_printf("%-*s ", NAME_LENGTH, ah->sender);
break;
case 5:
if (ah->subj_length > (lsubj - NAME_LENGTH - 5))
if (fmt_rptsubj || lno == firstl || (ah->flag & A_SAME) == 0) {
so_printf(" ");
lsubj -= 2;
break;
}
/* else use layout 1, so fall thru */
case 1:
lsubj -= NAME_LENGTH + 5;
/* name.lines. .subj (name may be shortened) */
lname = NAME_LENGTH + 2 - lnum;
so_printf("%-*.*s ", lname, lname, ah->sender);
so_printf(ah->lines >= 0 ? "%d " : "? ", ah->lines);
break;
case 2:
lsubj -= 6;
so_printf("%5d ", ah->lines);
break;
case 3:
break;
case 4:
lsubj -= 9;
so_printf("%-8.8s ", ah->sender);
break;
}
if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
if (ah->replies == 0 || prt_replies(ah->replies) == 0)
so_printf("-");
} else {
lsubj -= prt_replies(ah->replies);
if (lsubj >= ah->subj_length)
so_printf("%s", ah->subject);
else
if (collapse_subject < 0)
so_printf("%-.*s", lsubj, ah->subject);
else {
if (collapse_subject > 0)
so_printf("%-.*s", collapse_subject, ah->subject);
lsubj -= 2 + collapse_subject;
so_printf("<>%s", ah->subject + ah->subj_length - lsubj);
}
}
if (fmt_linenum == 0)
so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
so_end();
} else {
gotoxy(1, lno);
putchar((how == OFF) ? ' ' : '*');
}
return;
}
static prt_replies(level)
{
int re;
if (level == 0) return 0;
re = level & 0x80;
level &= 0x7f;
switch (re_layout) {
case 1:
if (!re) return 0;
so_printf(">");
return 1;
case 2:
so_printf("%d>", level);
return level < 10 ? 2 : 3;
case 3:
so_printf("Re: ");
return 4;
}
if (level < 10) {
so_printf("%-.*s", level, ">>>>>>>>>");
return level;
}
so_printf(">>>%3d >>>>", level);
return 11;
}
static int article_id;
static int get_k_cmd()
{
register int c, map;
loop:
article_id = -1;
if ((c = get_c()) & GETC_COMMAND)
map = c & ~GETC_COMMAND;
else
map = menu_key_map[c];
if (s_hangup) map = K_QUIT;
if (map & K_MACRO) {
m_invoke(map & ~K_MACRO);
goto loop;
}
if (map & K_ARTICLE_ID) {
article_id = map & ~K_ARTICLE_ID;
map = K_ARTICLE_ID;
if (article_id < 0 || article_id > numa) {
ding();
goto loop;
}
}
return map;
}
char *pct(start, end, first, last)
long start, end, first, last;
{
long n = end - start;
static char buf[16];
char *fmt;
if (first <= start || n <= 0)
if (last >= end || n <= 0)
return "All";
else
fmt = "Top %d%%";
else
if (last >= end)
return "Bot";
else
fmt = "%d%%";
sprintf(buf, fmt, ((last - start) * 100)/n);
return buf;
}
menu(print_header)
int (* print_header)();
{
register k_cmd, cur_k_cmd;
register article_header *ah;
int last_k_cmd, last_how;
int seen_all, menu_cmd, temp;
int save_selected;
article_number last_save;
int doing_unshar, did_unshar;
char *fname, *savemode, *init_save();
article_number nexta; /* first article on next menu */
int maxa; /* max no of articles per menu page */
int o_firsta, o_mode; /* for recursive calls */
static menu_level = 0;
char purpose[80], pr_fmt[60];
extern int enable_stop, file_completion();
extern int alt_cmd_key, in_menu_mode, any_message;
article_number elim_list[3];
int entry_check = conf_group_entry;
#define menu_return(cmd) \
{ menu_cmd = (cmd); goto menu_exit; }
flush_input();
o_firsta = firsta;
o_mode = in_menu_mode;
in_menu_mode = 1;
menu_level++;
sprintf(pr_fmt,
menu_level == 1 ?
"\1\2-- SELECT %s-----%%s-----\1" :
"\1\2-- SELECT %s-----%%s-----<%s%d>--\1",
novice ? "-- help:? " : "",
novice ? "level " : "",
menu_level);
purpose[0] = NUL;
if (!merged_menu && current_group->group_flag & G_NEW)
get_purpose(purpose);
seen_all = 0;
firsta = 0;
while (firsta < n_articles && articles[firsta]->flag & A_SEEN)
firsta++;
if (firsta == n_articles) {
seen_all++;
firsta = 0;
}
next_cura = -1;
cur_k_cmd = K_UNBOUND;
#ifdef HAVE_JOBCONTROL
#define REDRAW_CHECK if (s_redraw) goto do_redraw
do_redraw:
/* safe to clear here, because we are going to redraw anyway */
s_redraw = 0;
#else
#define REDRAW_CHECK
#endif
redraw:
s_keyboard = 0;
empty_menu_hack: /* do: "s_keyboard=1; goto empty_menu_hack;" */
if (!slow_mode) s_keyboard = 0;
nexta = firsta;
clrdisp();
firstl = (*print_header)();
maxa = Lines - preview_window - firstl - 2;
if (!long_menu) firstl++, maxa -= 2;
if (maxa > (INTERVAL1 + INTERVAL2))
maxa = INTERVAL1 + INTERVAL2;
nextmenu:
no_raw();
gotoxy(0, firstl);
clrpage(firstl);
if (nexta > 0) {
while (firsta < nexta)
articles[firsta++]->flag |= A_SEEN;
} else
if (purpose[0]) {
msg(purpose);
}
firsta = nexta;
numa = Lines; /* for mark; is set correctly below */
cura = 0;
REDRAW_CHECK;
if (!s_keyboard)
while (nexta < n_articles && cura < maxa) {
REDRAW_CHECK;
if (entry_check && menu_level == 1 &&
(current_group->group_flag & G_READ) == 0) {
entry_check = 0;
prompt_line = firstl;
prompt("\1Enter?\1 ");
if ((temp = yes(0)) == 0) menu_return(ME_NEXT);
if (temp < 0) {
prompt("\1Mark as read?\1 ");
if ((temp = yes(0)) > 0) menu_return(ME_READ);
if (temp < 0) menu_return(ME_QUIT);
menu_return(ME_NEXT);
}
gotoxy(0, firstl);
clrline();
}
how = INIT;
mark(); /* fl; */
if (s_keyboard) { /* Signal may have corrupted output. */
if (cura == 0)
mark(); /* redraw first entry */
else {
how = REMOVE; /* We delete the last entry (the user */
mark(); /* wanted to stop the output anyway) */
cura--;
nexta--;
}
break;
}
nexta++; cura++;
}
fl;
s_keyboard = 0;
prompt_line = firstl + cura;
if (!long_menu || cura < maxa) prompt_line++;
numa = nexta - firsta - 1;
if (numa < 0) prompt_line++;
if (next_cura >= 0) {
cura = next_cura;
next_cura = -1;
} else {
cura = 0;
for (article_id = firsta; cura < numa; article_id++, cura++)
if ((articles[article_id]->flag & A_SELECT) == 0) break;
}
how = TOGGLE;
build_prompt:
raw();
Prompt:
prompt(pr_fmt,
pct(0L, (long)(n_articles-1), (long)firsta, (long)(firsta+numa)));
if (delayed_msg != NULL) {
msg(delayed_msg, dl_msg_arg);
delayed_msg = NULL;
}
same_prompt:
if (cura < 0 || cura > numa) cura = 0;
if (numa >= 0) {
gotoxy(0, firstl + cura);
fl; /* place cursor at current article id */
save_xy();
}
last_k_cmd = cur_k_cmd;
k_cmd = get_k_cmd();
if (any_message) clrmsg(-1);
alt_key:
switch (cur_k_cmd = k_cmd) {
case K_UNBOUND:
ding();
flush_input();
case K_INVALID:
goto same_prompt;
case K_REDRAW:
next_cura = cura;
goto redraw;
case K_LAST_MESSAGE:
msg((char *)NULL);
goto same_prompt;
case K_HELP:
if (numa < 0) goto nextmenu; /* give specific help here */
display_help("menu");
goto redraw;
case K_SHELL:
if (group_file_name) *group_file_name = NUL;
if (shell_escape()) goto redraw;
goto Prompt;
case K_VERSION:
prompt(P_VERSION);
goto same_prompt;
case K_EXTENDED_CMD:
switch (alt_command()) {
case AC_UNCHANGED:
goto same_prompt;
case AC_QUIT:
menu_return( ME_QUIT );
case AC_PROMPT:
goto Prompt;
case AC_REORDER:
firsta = 0;
/* fall thru */
case AC_REDRAW:
goto redraw;
case AC_KEYCMD:
k_cmd = alt_cmd_key;
goto alt_key;
case AC_HEADER:
home();
(*print_header)();
goto Prompt;
}
case K_QUIT:
menu_return(ME_QUIT);
case K_CANCEL:
savemode = "Cancel";
fname = "";
goto cancel1;
case K_SAVE_NO_HEADER:
case K_SAVE_SHORT_HEADER:
case K_SAVE_FULL_HEADER:
case K_PRINT:
case K_UNSHAR:
case K_PATCH:
case K_UUDECODE:
if (numa < 0) goto nextmenu;
fname = init_save(k_cmd, &savemode);
if (fname == NULL) goto Prompt;
cancel1:
enable_stop = 0;
save_selected = 0;
doing_unshar = k_cmd == K_UNSHAR || k_cmd == K_PATCH;
did_unshar = 0;
m_startinput();
if (novice)
msg(" * selected articles on this page, + all selected articles");
while (!save_selected && !did_unshar) {
prompt("\1%s\1 %.*s Article (* +): ",
savemode, Columns - 25, fname);
k_cmd = get_k_cmd();
if (k_cmd == K_SELECT_SUBJECT) {
save_selected = 1;
cura = 0;
article_id = firsta;
last_save = firsta + numa;
} else
if (k_cmd == K_AUTO_SELECT) {
save_selected = 2;
cura = -firsta;
article_id = 0;
last_save = n_articles - 1;
} else
if (k_cmd == K_ARTICLE_ID) {
cura = article_id;
article_id += firsta;
last_save = article_id;
} else
break;
for ( ; article_id <= last_save ; article_id++, cura++) {
ah = articles[article_id];
if (save_selected && (ah->flag & A_SELECT) == 0) continue;
if (cur_k_cmd == K_CANCEL) {
if (current_group->group_flag & G_FOLDER) {
if ((ah->flag & A_CANCEL) == 0) fcancel(ah);
} else
switch (cancel(ah)) {
case -1:
did_unshar = 1;
continue;
case 0:
ah->flag |= A_CANCEL;
break;
default:
continue;
}
if (!did_unshar) {
how = CANCEL;
mark();
}
continue;
}
if (doing_unshar) {
did_unshar++;
} else
if (cura >= 0 && cura <= numa)
prompt("Processing %c...", ident[cura]);
else if (ah->subject != NULL)
prompt("Processing '%.50s'...", ah->subject);
else
prompt("Processing entry %d...", article_id);
if (save(ah)) {
if (doing_unshar) {
if (save_selected)
ah->flag &= ~(A_SELECT | A_AUTO);
} else
if (cura >= 0 && cura <= numa) {
how = save_selected ? OFF : SAVED;
mark();
how = TOGGLE;
} else
if (save_selected)
ah->flag &= ~(A_SELECT | A_AUTO);
}
}
}
if (save_selected) cura = 0;
how = TOGGLE;
m_endinput();
enable_stop = 1;
if (cur_k_cmd != K_CANCEL)
end_save();
if (did_unshar) {
printf("\r\n");
any_key(0);
goto redraw;
}
goto Prompt;
case K_FOLLOW_UP:
#ifdef NNTP_POST
if (use_nntp && nntp_no_post()) goto same_prompt;
#endif
case K_REPLY:
if (numa < 0) goto nextmenu;
prompt(k_cmd == K_REPLY ?
"\1Reply to author\1 of article: " :
"\1Follow Up\1 to article: ");
if (get_k_cmd() == K_ARTICLE_ID)
if (answer(articles[firsta+article_id], k_cmd, -1))
goto redraw;
goto Prompt;
case K_POST:
#ifdef NNTP_POST
if (use_nntp && nntp_no_post())
goto same_prompt;
#endif
if (post_menu()) goto redraw;
goto Prompt;
case K_MAIL_OR_FORWARD:
if (numa < 0) goto nextmenu;
prompt("\1Article to be forwarded\1 (SP if none): ");
if ((k_cmd = get_k_cmd()) == K_ARTICLE_ID) {
if (answer(articles[firsta+article_id], K_MAIL_OR_FORWARD, 1))
goto redraw;
} else
if (k_cmd == K_CONTINUE)
if (answer((article_header *)NULL, K_MAIL_OR_FORWARD, 0))
goto redraw;
goto Prompt;
/*
case K_CANCEL:
if (numa < 0) goto nextmenu;
if (current_group->group_flag & G_FOLDER) {
prompt("\1Cancel Folder\1 Article: ");
if (get_k_cmd() == K_ARTICLE_ID) {
cura = article_id;
fcancel(articles[firsta+article_id]);
how = CANCEL;
mark();
}
goto Prompt;
}
prompt("\1Cancel\1 Article: ");
if (get_k_cmd() == K_ARTICLE_ID)
if (cancel(articles[firsta+article_id]) & 1) goto redraw;
goto Prompt;
*/
case K_UNSUBSCRIBE:
if (unsubscribe(current_group)) {
if (!(current_group->group_flag & G_SUBSCRIPTION))
menu_return(ME_NEXT);
home();
(*print_header)();
}
goto Prompt;
case K_GROUP_OVERVIEW:
group_overview(-1);
goto redraw;
case K_KILL_HANDLING:
switch (kill_menu((article_header *)NULL)) {
case 0: /* select */
do_auto_select((regexp *)NULL, 2);
break;
case 1: /* kill */
if (!do_auto_kill()) break;
elim_list[0] = firsta;
elim_list[1] = firsta + cura;
elim_list[2] = nexta;
if (elim_articles(elim_list, 3)) {
firsta = elim_list[0];
goto redraw;
}
firsta = elim_list[0];
cura = elim_list[1] - firsta;
nexta = elim_list[2];
break;
default:
break;
}
goto Prompt;
case K_CONTINUE: /* goto next menu page or show the articles */
if (nexta < n_articles && !seen_all) goto nextmenu;
/* fall thru */
case K_READ_GROUP_UPDATE:
case K_READ_GROUP_THEN_SAME:
no_raw();
clrdisp();
switch (show_articles()) {
case SH_MENU:
goto redraw;
case SH_QUIT:
menu_return(ME_QUIT);
case SH_NO_SELECT:
break;
case SH_NEXT:
menu_return(ME_NEXT);
case SH_READ:
if (k_cmd == K_READ_GROUP_THEN_SAME || also_read_articles) goto redraw;
break;
default:
user_error("show_articles returned improper value");
}
menu_return(ME_READ);
case K_NEXT_GROUP_NO_UPDATE:
menu_return(ME_NEXT);
case K_PREVIOUS:
menu_return(ME_PREV);
case K_ADVANCE_GROUP:
case K_BACK_GROUP:
if (merged_menu) {
msg("No possible on merged menu");
goto same_prompt;
}
/* FALL THRU */
case K_GOTO_GROUP:
switch (goto_group(k_cmd, (article_header *)NULL)) {
case ME_REDRAW:
firsta = 0;
goto redraw;
case ME_NO_ARTICLES:
msg("No selections made.");
case ME_NO_REDRAW:
goto Prompt;
case ME_QUIT:
menu_return( ME_QUIT );
case ME_PREV:
goto redraw;
case ME_NEXT:
case ME_READ:
s_keyboard = 1;
goto empty_menu_hack;
}
case K_ARTICLE_ID:
if (numa < 0) goto nextmenu;
if (auto_preview_mode) goto auto_preview;
cura = article_id;
how = TOGGLE;
mark();
last_how = how;
cura++;
goto same_prompt;
case K_SELECT_INVERT:
if (numa < 0) goto nextmenu;
temp = cura;
no_raw(); /* for x-on/x-off */
for (cura = 0; cura <= numa; cura++) {
how = TOGGLE;
mark();
}
fl;
REDRAW_CHECK;
raw();
how = TOGGLE; cura = temp;
goto same_prompt;
case K_SELECT:
if (numa < 0) goto nextmenu;
how = TOGGLE;
mark();
last_how = how;
cura++;
goto same_prompt;
case K_UNSELECT_ALL:
for (cura = -firsta; cura < n_articles - firsta; cura++) {
if (last_k_cmd == K_UNSELECT_ALL) {
if ((articles[firsta + cura]->flag & (A_LEAVE | A_LEAVE_NEXT)) == 0)
continue;
articles[firsta + cura]->flag &= ~(A_LEAVE | A_LEAVE_NEXT);
how = ON_LEAVE;
} else
how = OFF;
mark();
}
fl;
cura = 0;
goto same_prompt;
case K_NEXT_LINE:
if (numa < 0) goto nextmenu;
cura++;
how = TOGGLE;
goto same_prompt;
case K_PREV_LINE:
if (numa < 0) goto nextmenu;
if (--cura < 0) cura = numa;
how = TOGGLE;
goto same_prompt;
case K_SELECT_SUBJECT:
if (numa < 0) goto nextmenu;
mark();
while (firsta+cura > 0 && articles[firsta+cura]->flag & A_SAME)
cura--;
do {
mark();
cura++;
if (firsta+cura >= n_articles) break;
} while (articles[firsta+cura]->flag & A_SAME);
how = TOGGLE;
goto same_prompt;
case K_SELECT_RANGE:
if (numa < 0) goto nextmenu;
if (last_k_cmd == K_ARTICLE_ID || last_k_cmd == K_SELECT) {
how = last_how;
cura--;
if (cura < 0) cura = numa;
} else
how = articles[firsta+cura]->flag & A_SELECT ? OFF : ON;
range_again:
prompt("\1%select range\1 %c-", how == ON ? "S" : "Des", ident[cura]);
k_cmd = get_k_cmd();
if (k_cmd == K_SELECT_RANGE) {
how = !how;
goto range_again;
}
if (k_cmd != K_ARTICLE_ID) goto Prompt;
if (last_k_cmd != K_ARTICLE_ID && last_k_cmd != K_SELECT)
mark();
if (article_id <= cura) {
while (--cura >= article_id) mark();
if (cura < 0) cura = 0;
} else {
while (++cura <= article_id) mark();
if (cura > numa) cura = numa;
}
how = TOGGLE;
goto Prompt;
case K_AUTO_SELECT:
do_auto_select((regexp *)NULL, 1);
goto same_prompt;
case K_GOTO_MATCH:
prompt("\1Select regexp\1 ");
if ((fname = get_s(NONE, NONE, NONE, NO_COMPLETION)) == NULL)
goto Prompt;
if (*fname != NUL) {
if (regular_expr) free((char *)regular_expr);
regular_expr = regcomp(fname);
}
if (regular_expr == NULL)
msg("No previous expression");
else
do_auto_select(regular_expr, 2);
goto Prompt;
case K_NEXT_PAGE:
if (nexta < n_articles) goto nextmenu;
if (firsta == 0) goto same_prompt;
seen_all++;
nexta = 0;
goto nextmenu;
case K_PREV_PAGE:
if (firsta == 0 && nexta == n_articles) goto same_prompt;
nexta = (firsta > 0 ? firsta : n_articles) - maxa;
if (nexta <= 1) nexta = 0;
goto nextmenu;
case K_FIRST_PAGE:
if (firsta == 0) goto same_prompt;
nexta = 0;
goto nextmenu;
case K_LAST_PAGE:
if (nexta == n_articles) goto same_prompt;
nexta = n_articles - maxa;
if (nexta <= 1) nexta = 0;
goto nextmenu;
case K_PREVIEW:
if (numa < 0) goto nextmenu;
preview_other:
prompt("\1Preview article\1");
k_cmd = get_k_cmd();
if (k_cmd != K_ARTICLE_ID) {
if (k_cmd != K_PREVIEW)
goto Prompt;
article_id = cura;
}
auto_preview:
temp = prompt_line;
preview_next:
cura = article_id;
ah = articles[firsta+cura];
no_raw();
menu_cmd = more(ah, MM_PREVIEW, prompt_line);
if (auto_preview_mode && ah->flag & A_READ && prompt_line >= 0) {
how = ON_READ;
mark();
}
next_cura = ++cura;
switch (menu_cmd) {
case MC_DO_KILL:
if (!do_auto_kill()) break;
elim_list[0] = firsta;
elim_list[1] = firsta + cura;
elim_articles(elim_list, 2);
firsta = elim_list[0];
next_cura = elim_list[1] - firsta;
goto redraw;
case MC_DO_SELECT:
if (prompt_line >= 0) { /* not redrawn */
do_auto_select((regexp *)NULL, 2);
break;
}
numa = -1;
do_auto_select((regexp *)NULL, 2);
/* FALL THRU */
case MC_QUIT:
menu_return( ME_QUIT );
case MC_NEXT: /* article not found -- preview next */
if (prompt_line == temp)
break; /* not redrawn -- return to menu instead */
user_delay(1);
/* FALL THRU */
case MC_PREVIEW_NEXT:
if (prompt_line < 0) { /* redrawn screen ! */
if ((firsta + cura) >= n_articles) goto redraw;
if (auto_preview_mode &&
(articles[firsta+cura]->flag & A_SAME) == 0) goto redraw;
prompt_line = Lines;
} else {
if (ah->flag & (A_LEAVE | A_LEAVE_NEXT)) {
cura--;
how = ON_LEAVE;
mark();
cura++;
}
if (cura > numa) break;
if (auto_preview_mode &&
(articles[firsta+cura]->flag & A_SAME) == 0) break;
prompt_line = temp;
}
article_id = cura;
goto preview_next;
case MC_PREVIEW_OTHER:
prompt_line = temp;
raw();
goto preview_other;
default:
if (prompt_line < 0) goto redraw;
break;
}
prompt_line = temp;
goto build_prompt;
case K_LAYOUT:
if (++fmt_linenum > 3) fmt_linenum = 0;
goto redraw;
default:
msg("Command %d not supported", k_cmd);
goto same_prompt;
}
menu_exit:
firsta = o_firsta;
in_menu_mode = o_mode;
menu_level--;
no_raw();
return menu_cmd;
}
static show_articles()
{
register article_number cur, next, temp;
register article_header *ah;
article_number elim_list[1];
register int mode;
int cmd, prev = -1, again;
do {
again = 0;
for (cur = 0; cur < n_articles; cur++) {
if (articles[cur]->flag & A_SELECT) break;
}
while (cur < n_articles) {
for (next = cur+1; next < n_articles; next++) {
if (articles[next]->flag & A_SELECT) break;
}
articles[cur]->flag &= ~(A_SELECT | A_AUTO);
show:
mode = 0;
if (prev >= 0) mode |= MM_PREVIOUS;
if (next == n_articles) mode |= MM_LAST_SELECTED;
if ((cur + 1) >= n_articles) mode |= MM_LAST_ARTICLE;
if (cur == 0) mode |= MM_FIRST_ARTICLE;
cmd = more(ah = articles[cur], mode, 0);
switch(cmd) {
case MC_DO_KILL:
if (do_auto_kill()) {
elim_list[0] = next;
elim_articles(elim_list, 1);
cur = elim_list[0];
if (cur < 0) cur = n_articles;
continue;
}
break;
case MC_DO_SELECT:
for (temp = cur+1, cur = next; temp < n_articles; temp++) {
if (auto_select_article(ah = articles[temp], 2)) {
ah->flag |= A_SELECT;
if (temp < cur) cur = temp;
}
}
continue;
case MC_PREV:
if (prev == next) break;
next = cur; cur = prev; prev = next;
goto show;
case MC_NEXTSUBJ:
ah->flag |= A_READ;
for (next = cur+1; next < n_articles; next++) {
if (((ah = articles[next])->flag & A_SAME) == 0) break;
ah->flag &= ~(A_SELECT | A_AUTO | A_LEAVE | A_LEAVE_NEXT);
}
for (; next < n_articles; next++) {
if (articles[next]->flag & A_SELECT) break;
}
break;
case MC_ALLSUBJ:
for (next = cur+1; next < n_articles; next++) {
ah = articles[next];
if ((ah->flag & A_SAME) == 0) break;
ah->flag &= ~(A_AUTO | A_LEAVE | A_LEAVE_NEXT | A_READ);
ah->flag |= A_SELECT;
}
for (next = cur+1; next < n_articles; next++)
if (articles[next]->flag & A_SELECT) break;
break;
case MC_MENU:
ah->flag |= A_SELECT;
firsta = cur - 5;
if (firsta < 0) firsta = 0;
next_cura = cur - firsta;
return SH_MENU;
case MC_QUIT:
ah->flag |= A_SELECT;
return SH_QUIT;
case MC_NEXT:
if ((ah->flag & (A_LEAVE | A_LEAVE_NEXT)) == 0)
ah->flag |= A_READ;
break;
case MC_BACK_ART:
if (cur > 0) {
next = cur - 1;
break;
}
goto show;
case MC_FORW_ART:
next = cur + 1;
break;
case MC_NEXTGROUP:
ah->flag |= A_SELECT;
return SH_NEXT;
case MC_READGROUP:
return SH_READ;
}
prev = cur; cur = next;
}
for (cur = 0; cur < n_articles; cur++)
if (articles[cur]->flag & A_SELECT) continue;
for (cur = 0; cur < n_articles; cur++) {
ah = articles[cur];
if (ah->flag & A_LEAVE) {
ah->flag &= ~A_LEAVE;
ah->flag |= A_SELECT;
again++;
}
}
if (again > 1) {
delayed_msg = "Showing %ld articles again";
dl_msg_arg = again;
} else
if (again == 1)
delayed_msg = "Showing article again";
} while (again);
return prev < 0 ? SH_NO_SELECT : SH_READ;
}
/*
* return article header for article on menu
*/
article_header *get_menu_article()
{
register article_header *ah;
fputs(" from article: ", stdout); fl;
if (get_k_cmd() == K_ARTICLE_ID) {
ah = articles[firsta + article_id];
if (ah->a_group) init_group(ah->a_group);
return ah;
}
return NULL;
}
static get_purpose(purpose)
char *purpose;
{
#ifdef NNTP
return; /* newsgroups file is not available */
#else
FILE *f;
char line[256], group[80];
register char *cp, *pp;
register int len;
extern char news_active[];
strcpy(line, news_active);
if ((cp = strrchr(line, '/')) == NULL) return;
strcat(cp + 1, "newsgroups");
if ((f = fopen(line, "r")) == NULL) return;
sprintf(group, "%s\t", current_group->group_name);
len = current_group->group_name_length + 1;
while (fgets(line, 256, f) != NULL) {
if (strncmp(line, group, len)) continue;
cp = line + len;
while (*cp && isspace(*cp)) cp++;
for (pp = purpose, len = 76; --len >= 0 && *cp && *cp != NL; )
*pp++ = *cp++;
*pp = NUL;
}
fclose(f);
#endif
}
/*
* perform auto selections that are not already selected
* if article is in range firsta..firsta+numa (incl) mark article
*/
static do_auto_select(re, mode)
regexp *re;
int mode;
{
register article_number i;
register article_header *ah, **ahp;
int count = 0, o_cura;
o_cura = cura;
for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
ah = *ahp;
if (re != NULL) {
if (!regexec(re, ah->subject)) continue;
} else
if (!auto_select_article(ah, mode)) continue;
count++;
if (ah->flag & A_SELECT) continue;
if (firsta <= i && i <= (firsta+numa)) {
cura = i - firsta;
how = ON;
mark();
} else
ah->flag |= A_SELECT;
}
msg(count == 0 ? "No selections" : "Selected %d article%s",
count, count > 1 ? "s" : "");
cura = o_cura;
}
static do_auto_kill()
{
register article_number i;
register article_header *ah, **ahp;
int any = 0;
for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
ah = *ahp;
if (auto_select_article(ah, 0)) {
ah->flag |= A_KILL;
ah->flag &= ~(A_SELECT | A_AUTO);
any = 1;
}
}
return any;
}
/*
* read command from command line
*/
alt_command()
{
int ok_val, macro_cmd;
char *cmd, brkchars[10];
extern char erase_key;
extern int get_from_macro;
extern int alt_completion();
if (get_from_macro)
ok_val = AC_UNCHANGED;
else {
prompt(":");
ok_val = AC_PROMPT;
}
again:
sprintf(brkchars, "?%c ", erase_key);
cmd = get_s(NONE, NONE, brkchars, alt_completion);
if (cmd == NULL ||
*cmd == NUL || *cmd == SP || *cmd == erase_key)
return ok_val;
macro_cmd = get_from_macro;
if (*cmd == '?') {
display_file("help.extended", CLEAR_DISPLAY);
ok_val = AC_REDRAW;
goto new_prompt;
}
ok_val = parse_command(cmd, ok_val, (FILE *)NULL);
if (ok_val != AC_REDRAW || !delay_redraw) return ok_val;
new_prompt:
if (macro_cmd) return ok_val;
prompt_line = -1;
printf("\n\r:");
fl;
goto again;
}